﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;
using System.Threading.Tasks;
using WinScriptEngine.Parses.Interface;
using WinScriptEngine.Parses.Scope;

namespace WinScriptEngine.Parses.Impl
{
    class WordParseException : UndefinedException
    {
        public WordParseException(string message) : base(message) { }
        public WordParseException(string message, Exception inner) : base(message, inner) { }
        protected WordParseException(SerializationInfo info, StreamingContext context) : base(info, context) { }
    }

    /// <summary>
    /// 符号解析类
    /// </summary>
    class SymbolParseImpl : SingletonObject<SymbolParseImpl>, IParse
    {
        public string VTypeName => "Word";

        public bool Invoke(InvokeEnvironment vCpu)
        {
            if (vCpu.needNumber < 1)
                throw new NumberRuntimeException("此处应为运算符");

            vCpu.results.Push(vCpu.instructions[vCpu.eip]);
            --vCpu.needNumber;
            return true;
        }
        public Metadata Parse(ref Metadata upper, IEnumerator<char> position)
        {
            StringBuilder builder = new();
            builder.Append(position.Current);
            // 添加直至检查不通过
            while (position.MoveNext() && CheckBody(position.Current))
            {
                builder.Append(position.Current);
            };

            string word = builder.ToString();
            if (word == "@")
                throw new WordParseException("@后面应为关键字、描述符、字符串");

            return new Metadata(MetadataType.Symbol,word);
        }

        /// <summary>
        /// 检查符号身体拼写
        /// </summary>
        /// <param name="curChar">身体字符</param>
        /// <returns>是否合法</returns>
        protected bool CheckBody(char curChar)
        {
            return curChar >= 'a' && curChar <= 'z'
                || curChar >= 'A' && curChar <= 'Z'
                || curChar >= '0' && curChar <= '9'
                || curChar == '_';
        }
        
        public bool TryParse(ref Metadata upper, char curChar)
        {
            return curChar >= 'a' && curChar <= 'z'
                || curChar >= 'A' && curChar <= 'Z'
                || curChar == '@'
                || curChar == '_';
        }

    }
}
